﻿using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Lime49;
using Lime49.UI;
using LockCrypt.Core;
using LockCrypt.Properties;

namespace LockCrypt {
    /// <summary>
    /// Dialog for exporting databases.
    /// </summary>
    public partial class WinExport : Window {
        //private SaveFileDialog dlgSave;

        public static DependencyProperty FileTypeProperty = DependencyProperty.Register("FileType", typeof(Constants.DataType), typeof(WinExport), new PropertyMetadata(Constants.DataType.XML));
        /// <summary>
        /// Gets the type of file selected.
        /// </summary>
        /// <value>The type of file selected..</value>
        public Constants.DataType FileType {
            get { return (Constants.DataType)base.GetValue(FileTypeProperty); }
            set { base.SetValue(FileTypeProperty, value); }
        }

        public static DependencyProperty SelectedFileProperty = DependencyProperty.Register("SelectedFile", typeof(string), typeof(WinExport), new PropertyMetadata(string.Empty));
        /// <summary>
        /// Gets the name of the selected file.
        /// </summary>
        /// <value>The name of the selected file.</value>
        public string SelectedFile {
            get { return System.Convert.ToString(base.GetValue(SelectedFileProperty)); }
            set { base.SetValue(SelectedFileProperty, value); }
        }

        public static DependencyProperty EncryptionAlgorithmProperty = DependencyProperty.Register("EncryptionAlgorithm", typeof(EncryptionProviders), typeof(WinExport), new PropertyMetadata(EncryptionProviders.None));
        /// <summary>
        /// Gets the selected encryption algorithm.
        /// </summary>
        /// <value>The selected encryption algorithm.</value>
        public EncryptionProviders EncryptionAlgorithm {
            get { return (EncryptionProviders)base.GetValue(EncryptionAlgorithmProperty); }
            set { base.SetValue(EncryptionAlgorithmProperty, value); }
        }

        /// <summary>
        /// Gets the password entered.
        /// </summary>
        /// <value>The password entered.</value>
        public string Password {
            get { return txtPassword.Password; }
            set { txtPassword.Password = value; }
        }

        /// <summary>
        /// Initializes a new <see cref="WinExport"/>.
        /// </summary>
        public WinExport() {
            InitializeComponent();
            cboEncryption.ItemsSource = EnumBinder.EnumHelper.ToList<string>(typeof(EncryptionProviders));
            Dictionary<Constants.DataType, string> availableTypes = new Dictionary<Constants.DataType,string>() {
                { Constants.DataType.XML, I18nUtils.GetString("Strings", "XmlFile")},
                { Constants.DataType.SQLite, I18nUtils.GetString("Strings", "SQLiteDatabase")},
                { Constants.DataType.Legacy, I18nUtils.GetString("Strings", "LegacyDatabase")},
                { Constants.DataType.CSV, I18nUtils.GetString("Strings", "CsvFile")},
                { Constants.DataType.HTML, I18nUtils.GetString("Strings", "HtmlFile")}
            };
            lstType.ItemsSource = availableTypes;
            filenameChooser.FilterString = string.Format("{0}|*.*|{1} (*.xml)|*.lce;*.xml|{2} (*.lce)|*.lce;*.db3|{3} (*.lce)|*.lce|{4} (*.csv)|*.csv|{5} (*.html)|*.html;*.htm",
                                       I18nUtils.GetString("Strings", "AllFiles"),
                                       I18nUtils.GetString("Strings", "LockCryptDatabases"),
                                       I18nUtils.GetString("Strings", "SQLiteDatabases"),
                                       I18nUtils.GetString("Strings", "LegacyDatabase"),
                                       I18nUtils.GetString("Strings", "CsvFiles"),
                                       I18nUtils.GetString("Strings", "HtmlFiles"));
        }

        /// <summary>
        /// Initializes a new <see cref="WinExport"/>.
        /// </summary>
        /// <param name="type">The database type to pre-select.</param>
        /// <param name="encryption">The encryption algorithm to pre-select.</param>
        public WinExport(Constants.DataType type, EncryptionProviders encryption) 
            :this() {
            FileType = type;
            EncryptionAlgorithm = encryption;
            this.Loaded += (s, e) => UpdateFileExtension();
        }

        /// <summary>
        /// Closes the dialog if files have been selected.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void StartExport(object sender, ExecutedRoutedEventArgs e) {
            if(ValidateFilename()) {
                Settings.Default.Save();
                DialogResult = true;
            }
        }

        /// <summary>
        /// Closes the window.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void CloseWindow(object sender, ExecutedRoutedEventArgs e) {
            DialogResult = false;
        }

        /// <summary>
        /// Validates the filename entered.
        /// </summary>
        /// <returns><c>true</c> if the filename is valid, otherwise <c>false</c>.</returns>
        private bool ValidateFilename() {
            bool valid = true;
            if(string.IsNullOrEmpty(SelectedFile)) {
                DialogBox.ShowAlert(this, I18nUtils.GetString("Errors", "FilenameRequired"), I18nUtils.GetString("Errors", "Error"));
                valid = false;
            } else if(File.Exists(SelectedFile) && DialogBox.Show(this, I18nUtils.GetString("Strings", "FileExistsOverwritePrompt"), I18nUtils.GetString("Strings", "FileExists"), DialogBox.DialogBoxType.YesNo, DialogBox.DialogBoxIcon.Warning, DialogBoxButton.No) != DialogBoxButton.Yes) {
                valid = false;
            }
            return valid;
        }

        /// <summary>
        /// Disables modification of the encryption algorithm when legacy encryption is selected.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void lstType_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            switch(FileType) {
                case Constants.DataType.SQLite:
                case Constants.DataType.XML:
                    cboEncryption.IsEnabled = true;
                    break;
                case Constants.DataType.HTML:
                case Constants.DataType.CSV:
                    EncryptionAlgorithm = EncryptionProviders.None;
                    cboEncryption.IsEnabled = false;
                    break;
                case Constants.DataType.Legacy:
                    EncryptionAlgorithm = EncryptionProviders.Aes256;
                    cboEncryption.IsEnabled = false;
                    break;
                default:
                    EncryptionAlgorithm = EncryptionProviders.Aes256;
                    cboEncryption.IsEnabled = false;
                    break;
            }
            UpdateFileExtension();
        }

        private void cboEncryption_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            UpdateFileExtension();
        }

        /// <summary>
        /// Updates the file extension for the file picker and combobox.
        /// </summary>
        private void UpdateFileExtension() {
            if(!IsLoaded)
                return;
            switch(FileType) {
                case Constants.DataType.SQLite:
                    filenameChooser.DefaultExtension = ".lce";
                    filenameChooser.FilterIndex = 3;
                    break;
                case Constants.DataType.Legacy:
                    filenameChooser.DefaultExtension = ".lce";
                    filenameChooser.FilterIndex = 4;
                    break;
                case Constants.DataType.CSV:
                    filenameChooser.DefaultExtension = ".csv";
                    filenameChooser.FilterIndex = 5;
                    break;
                case Constants.DataType.HTML:
                    filenameChooser.DefaultExtension = ".html";
                    filenameChooser.FilterIndex = 6;
                    break;
                case Constants.DataType.XML:
                default:
                    filenameChooser.FilterIndex = 2;
                    if(EncryptionAlgorithm == EncryptionProviders.None) {
                        filenameChooser.DefaultExtension = ".xml";
                    } else {
                        filenameChooser.DefaultExtension = ".lce";
                    }
                    break;
            }
            try {
                if(SelectedFile.Length == 0)
                    return;
                string currentExtension = System.IO.Path.GetExtension(SelectedFile);
                string currentFilename = SelectedFile.Substring(0, SelectedFile.Length - currentExtension.Length);
                SelectedFile = currentFilename + "." + filenameChooser.DefaultExtension;
            } catch {
            }
        }
    }
}
